﻿using System;

using BrightSword.Crucible;
using BrightSword.SwissKnife;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tests.BrightSword.SwissKnife
{
    [TestClass]
    public class ObjectDescriberTests
    {
        [TestMethod]
        public void TestGetNameForAction()
        {
            Assert.AreEqual(
                "SomeAction",
                ObjectDescriber.GetName((Test _) => _.SomeAction()));
        }

        [TestMethod]
        public void TestGetNameForFunction()
        {
            Assert.AreEqual(
                "SomeFunction",
                ObjectDescriber.GetName((Test _) => _.SomeFunction()));
        }

        [TestMethod]
        public void TestGetNameForProperty()
        {
            Assert.AreEqual(
                "SomeProperty",
                ObjectDescriber.GetName((Test _) => _.SomeProperty));
        }

        [TestMethod]
        public void TestGetNameForStaticAction()
        {
            Assert.AreEqual(
                "SomeStaticAction",
                ObjectDescriber.GetName(() => Test.SomeStaticAction()));
        }

        [TestMethod]
        public void TestGetNameForStaticFunction()
        {
            Assert.AreEqual(
                "SomeStaticFunction",
                ObjectDescriber.GetName(() => Test.SomeStaticFunction()));
        }

        [TestMethod]
        public void TestGetNameForStaticProperty()
        {
            Assert.AreEqual(
                "SomeStaticProperty",
                ObjectDescriber.GetName(() => Test.SomeStaticProperty));
        }


        [TestMethod]
        public void TestGetNameForComplexExpressionFailsProperly()
        {
            ExceptionHelper.ExpectException<NotSupportedException>(() => ObjectDescriber.GetName(() => Test.SomeStaticProperty + "Hello"));
        }

        #region Nested type: Test

        private abstract class Test
        {
            public string SomeProperty { get; private set; }

            public static DateTime SomeStaticProperty { get { return DateTime.Now; } }

            public abstract void SomeAction();

            public int SomeFunction()
            {
                // bogus code to force SomeFunction to not be made static
                return int.Parse(SomeProperty);
            }

            public static void SomeStaticAction() { }

            public static int SomeStaticFunction() { return 42; }
        }

        #endregion
    }
}